﻿using CLM.Gestao.Administrador.BLL;
using CLM.Gestao.Administrador.DAL;
using CLM.Gestao.Importacao;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace CLM.Gestao.Vendas.BLL
{
    /// <summary>
    /// 
    /// </summary>
    public class Venda
    {
        #region Processos
        private const int MaxItens = 2500; 
        private DataSet dsVendas;

        private Importacao.Excel ExcelConnection;

        #region Sincronizar Vendas

        /// <summary>
        /// 
        /// </summary>
        private enum TipoProcesso
        {
            SincronizarVenda,
            ImportarVenda//,
            //CalcularAmostraGratisProcedimento
        }

        /// <summary>
        /// Sincronizar Venda
        /// </summary>
        /// <param name="pMes">Mês a ser sincronizado</param>
        /// <param name="pAno">Ano a ser sincronizado</param>
        public void SincronizarVenda(int pMes, int pAno)
        {
            try
            {
                OnImportData(this, new ImportDataEventArgs("Acessando Banco de Dados Protheus..."));

                // Altera a chamada para uma nova procedure 
                Protheus.BLL.SPVendasGalderma ProcedureVendas = new Protheus.BLL.SPVendasGalderma();

                List<Lista> VendasProtheus = (from v in ProcedureVendas.ExecutaProcedure(pMes, pAno)
                                              select new Lista
                                              {
                                                  CodigoCliente = v.CodigoCliente,
                                                  CodigoProduto = v.CodigoProduto,
                                                  Desconto = Convert.ToDecimal(v.Desconto),
                                                  Estado = v.Estado,
                                                  Liquido = Convert.ToDecimal(v.Liquido),
                                                  Mercadoria = Convert.ToDecimal(v.Mercadoria),
                                                  NomeCliente = v.NomeCliente,
                                                  NomeProduto = v.NomeProduto,
                                                  Nota = v.Nota,
                                                  Quantidade = Convert.ToInt32(v.Quantidade),
                                                  Repasse = Convert.ToDecimal(v.Repasse),
                                                  Serie = v.Serie,
                                                  Tipo = v.Tipo
                                              }).ToList();

                ProcessarVendas(VendasProtheus, pMes, pAno, TipoProcesso.SincronizarVenda);

                OnImportData(this, new ImportDataEventArgs("Sincronização efetuada com sucesso."));

                //ProcessarVendas(VendasProtheus, pMes, pAno, TipoProcesso.CalcularAmostraGratisProcedimento);

                //OnImportData(this, new ImportDataEventArgs("Amostra calculada com sucesso."));
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Importa Venda
        /// </summary>
        /// <param name="pFileName">Arquivo a ser importado</param>
        /// <param name="pMes">Mês a ser importado</param>
        /// <param name="pAno">Ano a ser importado</param>
        public void ImportarVenda(string pFileName, int pMes, int pAno)
        {
            try
            {
                ExcelConnection = new Importacao.Excel();
                dsVendas = null;

                ValidaLayoutImportacao(pFileName);

                OnImportData(this, new ImportDataEventArgs("Importando informações de Venda..."));

                // Dictionary de Produtos para recuperar o ID, utilizando o código
                Produto Produto = new Produto();
                var Produtos = Produto.GetItens().ToDictionary(d => d.CodigoProduto);

                // Colunas H, I, J, L, O, P, Z, AD
                var VendasExcel = (from v in dsVendas.Tables[0].AsEnumerable()
                                   join db in Produtos.Select(s => s.Value).ToList()
                                   on Convert.ToString(v.Field<object>("Produto")).PadLeft(9, '0') equals db.CodigoProduto.PadLeft(9, '0')
                                   select new Lista
                               {
                                   Nota = v.Field<object>("Nota").ToString(),
                                   Serie = v.Field<object>("Série").ToString(),
                                   CodigoCliente = v.Field<object>("Cliente").ToString(),
                                   NomeCliente = v.Field<string>("Nome").Trim(),
                                   Estado = v.Field<string>("Estado"),
                                   CodigoProduto = Convert.ToString(v.Field<object>("Produto")).PadLeft(9, '0'),
                                   Desconto = Convert.ToDecimal(v.Field<object>("Desconto")),
                                   Liquido = Convert.ToDecimal(v.Field<object>("Líquido")),
                                   Mercadoria = Convert.ToDecimal(v.Field<object>("Mercadoria")),
                                   NomeProduto = v.Field<string>("Descrição").Trim(),
                                   Quantidade = Convert.ToInt32(v.Field<object>("Quantidade")),
                                   Repasse = Convert.ToDecimal(v.Field<object>("Repasse")),
                                   Tipo = v.Field<string>("Tipo")
                               }).ToList();

                ProcessarVendas(VendasExcel, pMes, pAno, TipoProcesso.ImportarVenda);

                OnImportData(this, new ImportDataEventArgs("Importação efetuada com sucesso."));
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Valida Layout de Importação
        /// </summary>
        /// <param name="pFileName">Arquivo a ser importado</param>
        private void ValidaLayoutImportacao(string pFileName)
        {
            // Acessa o documento Excel e efetua a consulta na planilha "Dados"
            try { dsVendas = ExcelConnection.ExecuteRecordset(pFileName, "SELECT * FROM [Dados$]"); }
            catch { throw new Exception("A planilha não possui a aba \"Dados\"."); }

            if (dsVendas != null && dsVendas.Tables != null && dsVendas.Tables.Count > 0 && dsVendas.Tables[0].Rows.Count > 0)
            {
                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Nota"); }
                catch { throw new Exception("A coluna (\"Nota\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Série"); }
                catch { throw new Exception("A coluna (\"Série\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Cliente"); }
                catch { throw new Exception("A coluna (\"Cliente\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Nome"); }
                catch { throw new Exception("A coluna (\"Nome\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Estado"); }
                catch { throw new Exception("A coluna (\"Estado\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Produto"); }
                catch { throw new Exception("A coluna (\"Produto\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Desconto"); }
                catch { throw new Exception("A coluna (\"Desconto\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Líquido"); }
                catch { throw new Exception("A coluna (\"Líquido\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Mercadoria"); }
                catch { throw new Exception("A coluna (\"Mercadoria\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Descrição"); }
                catch { throw new Exception("A coluna (\"Descrição\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Quantidade"); }
                catch { throw new Exception("A coluna (\"Quantidade\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Repasse"); }
                catch { throw new Exception("A coluna (\"Repasse\") não foi encontrada no arquivo."); }

                try { var aux = dsVendas.Tables[0].Rows[0].Field<object>("Tipo"); }
                catch { throw new Exception("A coluna (\"Tipo\") não foi encontrada no arquivo."); }
            }
        }

        /// <summary>
        /// Processa Vendas
        /// </summary>
        /// <param name="pListaVendas">Lista de Vendas</param>
        /// <param name="pTipoProcesso">Tipo de processo a ser executado</param>
        private void ProcessarVendas(List<Lista> pListaVendas, int pMes, int pAno, TipoProcesso pTipoProcesso)
        {
            OnImportData(this, new ImportDataEventArgs("Validando dados..."));

            Lancamento Lancamento = new Lancamento();

            // Dictionary de Produtos para recuperar o ID, utilizando o código
            Produto Produto = new Produto();
            var Produtos = Produto.GetLista().ToDictionary(d => d.CodigoProduto);

            // Período do mês de importação
            Periodo Periodo = new Periodo();
            var IdPeriodo = Periodo.GetItens(new Periodo.Lista() { AnoPeriodo = pAno, MesPeriodo = pMes }).First().IdPeriodo;

            // Dictionary de Contas Contábeis para recuperar o ID, utilizando o código e a descrição
            ContaContabil ContaContabil = new ContaContabil();
            var CodigosContasContabeis = ContaContabil.GetItens(new ContaContabil.Lista() { IndicaGerencial = false }).GroupBy(g => g.CodigoContaContabil).Select(s => new ContaContabil.Lista { CodigoContaContabil = s.Key, IdContaContabil = s.FirstOrDefault().IdContaContabil }).ToDictionary(d => d.CodigoContaContabil);
            var DescricoesContasContabeis = ContaContabil.GetItens(new ContaContabil.Lista() { IndicaGerencial = true }).GroupBy(g => g.DescricaoContaContabil).Select(s => new ContaContabil.Lista { DescricaoContaContabil = s.Key, IdContaContabil = s.FirstOrDefault().IdContaContabil }).ToDictionary(d => d.DescricaoContaContabil);

            // Dictionary de Custos Unitários para recuperar o valor, utilizando o código
            CustoUnitario CustoUnitario = new CustoUnitario();
            var ValoresCustosUnitarios = CustoUnitario.GetLista().ToDictionary(d => d.CodigoProduto);

            // Dictionary de Centros de Custos para recuperar o ID, utilizando o ID
            CentroCusto CentroCusto = new CentroCusto();
            var CentrosCustos = CentroCusto.GetLista(new CentroCusto.Lista() { IndicaGerencial = false }).ToDictionary(d => d.IdCentroCusto);

            // Dictionary de Indicadores de Vendas para recuperar o ID, utilizando o nome
            IndicadorVenda IndicadorVenda = new IndicadorVenda();
            var IndicadoresVendas = IndicadorVenda.GetLista().ToDictionary(d => d.NomeIndicadorVenda);

            // Dictionary de Indicadores de Custos para recuperar o ID, utilizando o nome
            IndicadorCusto IndicadorCusto = new IndicadorCusto();
            var IndicadoresCustos = IndicadorCusto.GetLista().ToDictionary(d => d.NomeIndicadorCusto);

            // Dictionary de Indicadores de Despesas para recuperar o ID, utilizando o nome
            IndicadorDespesa IndicadorDespesa = new IndicadorDespesa();
            var IndicadoresDespesas = IndicadorDespesa.GetLista().ToDictionary(d => d.NomeIndicadorDespesa);

            ValidaDadosImportacao(Produtos, pListaVendas);

            OnImportData(this, new ImportDataEventArgs("Validação completa..."));

            ExcluirLancamentosAnteriores(pMes, pAno, pTipoProcesso);

            OnImportData(this, new ImportDataEventArgs("Iniciando processo..."));

            #region Indicador NetSales

            var Lancamentos = (from v in pListaVendas
                               select new TB_LANCAMENTO
                               {
                                   CONTRATO_DESPESA_COMPROMETIDA = null,
                                   DATA_INCLUSAO = DateTime.Now,
                                   DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                                   DESCRICAO_LANCAMENTO = string.Format("Saldo de vendas do período {0}/{1}", pMes, pAno),
                                   ID_CENTRO_CUSTO = null,
                                   ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresVendas.NetSales].IdContaContabil,
                                   ID_LANCAMENTO_TIPO = 1,
                                   ID_MAPA_ESTRATEGICO_ITEM = null,
                                   ID_PERIODO = IdPeriodo,
                                   ID_PROJETO = null,
                                   INDICA_DESPESA_COMPROMETIDA = false,
                                   // Fórmula para calcular o lançamento
                                   VALOR_LANCAMENTO =
                                        v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                        : Math.Round(v.Liquido, 6),
                                   TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
                                   {
                                       new TB_LANCAMENTO_VENDA()
                                       {
                                            ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.NetSales].IdIndicadorVenda,
                                            ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto,
                                            QUANTIDADE_VENDA = v.Quantidade,
                                            DESCONTO  = Convert.ToDouble(v.Desconto),
                                            LIQUIDO = Convert.ToDouble(v.Liquido),
                                            MERCADORIA = Convert.ToDouble(v.Mercadoria),
                                            REPASSE = Convert.ToDouble(v.Repasse),
                                            INDICA_PROVISAO = pTipoProcesso == TipoProcesso.ImportarVenda ? true : false,
                                            NOTA = v.Nota,
                                            SERIE = v.Serie,
                                            CODIGO_CLIENTE = v.CodigoCliente,
                                            NOME_CLIENTE = v.NomeCliente,
                                            ESTADO = v.Estado,
                                            TIPO = v.Tipo
                                       }
                                    }
                               }).ToList();

            int i = 0;
            int iMaxItens = 0;
            foreach (var item in Lancamentos)
            {
                Lancamento.Add(item);
                if (iMaxItens >= MaxItens)
                {
                    Lancamento.Save();
                    iMaxItens = 0;
                }
                i++;
                iMaxItens++;
                OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresVendas.NetSales + "...", i, Lancamentos.Count()));
            }
            Lancamento.Save();

            #endregion Indicador NetSales

            GC.Collect();

            #region Indicador OthCredRebV

            Lancamentos = (from v in pListaVendas
                           select new TB_LANCAMENTO
                           {
                               CONTRATO_DESPESA_COMPROMETIDA = null,
                               DATA_INCLUSAO = DateTime.Now,
                               DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                               DESCRICAO_LANCAMENTO = string.Format("Saldo de vendas do período {0}/{1}", pMes, pAno),
                               ID_CENTRO_CUSTO = null,
                               ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresVendas.OthCredRebV].IdContaContabil,
                               ID_LANCAMENTO_TIPO = 1,
                               ID_MAPA_ESTRATEGICO_ITEM = null,
                               ID_PERIODO = IdPeriodo,
                               ID_PROJETO = null,
                               INDICA_DESPESA_COMPROMETIDA = false,
                               // Fórmula para calcular o lançamento
                               VALOR_LANCAMENTO =
                                    v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                    : v.Tipo.ToUpper() == "DEVOLUCAO" ? 0
                                    : v.Tipo.ToUpper() == "DIF. PROVISÃO/LÇTO" ? 0
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_PROVISÃO" ? 0
                                    : v.Tipo.ToUpper() == "BONIFICADO" ? Decimal.Round(v.Mercadoria * (-1),6)
                                    : Math.Round(((v.Liquido / (1 - (v.Desconto - v.Repasse) / v.Mercadoria)) - v.Liquido) * (-1), 6),
                               TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
                                   {
                                       new TB_LANCAMENTO_VENDA()
                                       {
                                            ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.OthCredRebV].IdIndicadorVenda,
                                            ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto,
                                            QUANTIDADE_VENDA = v.Quantidade,
                                            DESCONTO  = Convert.ToDouble(v.Desconto),
                                            LIQUIDO = Convert.ToDouble(v.Liquido),
                                            MERCADORIA = Convert.ToDouble(v.Mercadoria),
                                            REPASSE = Convert.ToDouble(v.Repasse),
                                            INDICA_PROVISAO = pTipoProcesso == TipoProcesso.ImportarVenda ? true : false,
                                            NOTA = v.Nota,
                                            SERIE = v.Serie,
                                            CODIGO_CLIENTE = v.CodigoCliente,
                                            NOME_CLIENTE = v.NomeCliente,
                                            ESTADO = v.Estado,
                                            TIPO = v.Tipo
                                       }
                                   }
                           }).ToList();
            i = 0;
            iMaxItens = 0;
            foreach (var item in Lancamentos)
            {
                Lancamento.Add(item);
                if (iMaxItens >= MaxItens)
                {
                    Lancamento.Save();
                    iMaxItens = 0;
                }
                i++;
                iMaxItens++;
                OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresVendas.OthCredRebV + "...", i, Lancamentos.Count()));
            }
            Lancamento.Save();

            #endregion Indicador OthCredRebV

            GC.Collect();

            #region Indicador GSalesArV

            Lancamentos = (from v in pListaVendas
                           select new TB_LANCAMENTO
                           {
                               CONTRATO_DESPESA_COMPROMETIDA = null,
                               DATA_INCLUSAO = DateTime.Now,
                               DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                               DESCRICAO_LANCAMENTO = string.Format("Saldo de vendas do período {0}/{1}", pMes, pAno),
                               ID_CENTRO_CUSTO = null,
                               ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresVendas.GSalesArV].IdContaContabil,
                               ID_LANCAMENTO_TIPO = 1,
                               ID_MAPA_ESTRATEGICO_ITEM = null,
                               ID_PERIODO = IdPeriodo,
                               ID_PROJETO = null,
                               INDICA_DESPESA_COMPROMETIDA = false,
                               // Fórmula para calcular o lançamento
                               VALOR_LANCAMENTO =
                                    v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                    : Math.Round(v.Liquido
                                    - (v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                    : v.Tipo.ToUpper() == "DEVOLUCAO" ? 0
                                    : v.Tipo.ToUpper() == "DIF. PROVISÃO/LÇTO" ? 0
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_PROVISÃO" ? 0
                                    : v.Tipo.ToUpper() == "BONIFICADO" ? Math.Round(v.Liquido * (-1), 6)
                                    : v.Mercadoria == 0 ? 0
                                    : Math.Round(((v.Liquido / (1 - (v.Desconto - v.Repasse) / v.Mercadoria)) - v.Liquido) * (-1), 6)), 6),
                               TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
                                   {
                                       new TB_LANCAMENTO_VENDA()
                                       {
                                            ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.GSalesArV].IdIndicadorVenda,
                                            ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto,
                                            QUANTIDADE_VENDA = v.Quantidade,
                                            DESCONTO  = Convert.ToDouble(v.Desconto),
                                            LIQUIDO = Convert.ToDouble(v.Liquido),
                                            MERCADORIA = Convert.ToDouble(v.Mercadoria),
                                            REPASSE = Convert.ToDouble(v.Repasse),
                                            INDICA_PROVISAO = pTipoProcesso == TipoProcesso.ImportarVenda ? true : false,
                                            NOTA = v.Nota,
                                            SERIE = v.Serie,
                                            CODIGO_CLIENTE = v.CodigoCliente,
                                            NOME_CLIENTE = v.NomeCliente,
                                            ESTADO = v.Estado,
                                            TIPO = v.Tipo
                                       }
                                   }
                           }).ToList();

            i = 0;
            iMaxItens = 0;
            foreach (var item in Lancamentos)
            {
                Lancamento.Add(item);
                if (iMaxItens >= MaxItens)
                {
                    Lancamento.Save();
                    iMaxItens = 0;
                }

                i++;
                iMaxItens++;
                OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresVendas.GSalesArV + "...", i, Lancamentos.Count()));
            }
            Lancamento.Save();

            #endregion Indicador GSalesArV

            GC.Collect();

            #region Indicador ReturnsV

            Lancamentos = (from v in pListaVendas
                           select new TB_LANCAMENTO
                           {
                               CONTRATO_DESPESA_COMPROMETIDA = null,
                               DATA_INCLUSAO = DateTime.Now,
                               DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                               DESCRICAO_LANCAMENTO = string.Format("Saldo de vendas do período {0}/{1}", pMes, pAno),
                               ID_CENTRO_CUSTO = null,
                               ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresVendas.ReturnsV].IdContaContabil,
                               ID_LANCAMENTO_TIPO = 1,
                               ID_MAPA_ESTRATEGICO_ITEM = null,
                               ID_PERIODO = IdPeriodo,
                               ID_PROJETO = null,
                               INDICA_DESPESA_COMPROMETIDA = false,
                               // Fórmula para calcular o lançamento
                               VALOR_LANCAMENTO =
                                    v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                    : v.Tipo.ToUpper() == "DEVOLUCAO" ? Decimal.Round(v.Liquido,6)
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_PROVISÃO" ? Decimal.Round(v.Liquido,6)
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_ESTORNO_PROVISÃO" ? Decimal.Round(v.Liquido,6) : 0,
                               TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
                                   {
                                       new TB_LANCAMENTO_VENDA()
                                       {
                                            ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.ReturnsV].IdIndicadorVenda,
                                            ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto,
                                            QUANTIDADE_VENDA = v.Quantidade,
                                            DESCONTO  = Convert.ToDouble(v.Desconto),
                                            LIQUIDO = Convert.ToDouble(v.Liquido),
                                            MERCADORIA = Convert.ToDouble(v.Mercadoria),
                                            REPASSE = Convert.ToDouble(v.Repasse),
                                            INDICA_PROVISAO = pTipoProcesso == TipoProcesso.ImportarVenda ? true : false,
                                            NOTA = v.Nota,
                                            SERIE = v.Serie,
                                            CODIGO_CLIENTE = v.CodigoCliente,
                                            NOME_CLIENTE = v.NomeCliente,
                                            ESTADO = v.Estado,
                                            TIPO = v.Tipo
                                       }
                                   }
                           }).ToList();

            i = 0;
            iMaxItens = 0;
            foreach (var item in Lancamentos)
            {
                Lancamento.Add(item);
                if (iMaxItens >= MaxItens)
                {
                    Lancamento.Save();
                    iMaxItens = 0;
                }
                i++;
                iMaxItens++;
                OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresVendas.ReturnsV + "...", i, Lancamentos.Count()));
            }
            Lancamento.Save();

            #endregion Indicador ReturnsV

            GC.Collect();

            #region Indicador GSalesBrV

            Lancamentos = (from v in pListaVendas
                           select new TB_LANCAMENTO
                           {
                               CONTRATO_DESPESA_COMPROMETIDA = null,
                               DATA_INCLUSAO = DateTime.Now,
                               DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                               DESCRICAO_LANCAMENTO = string.Format("Saldo de vendas do período {0}/{1}", pMes, pAno),
                               ID_CENTRO_CUSTO = null,
                               ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresVendas.GSalesBrV].IdContaContabil,
                               ID_LANCAMENTO_TIPO = 1,
                               ID_MAPA_ESTRATEGICO_ITEM = null,
                               ID_PERIODO = IdPeriodo,
                               ID_PROJETO = null,
                               INDICA_DESPESA_COMPROMETIDA = false,
                               // Fórmula para calcular o lançamento
                               VALOR_LANCAMENTO =
                                    v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                    : Math.Round(v.Liquido
                                    - (v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                    : v.Tipo.ToUpper() == "DEVOLUCAO" ? 0
                                    : v.Tipo.ToUpper() == "DIF. PROVISÃO/LÇTO" ? 0
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_PROVISÃO" ? 0
                                    : v.Tipo.ToUpper() == "BONIFICADO" ? Math.Round(v.Mercadoria * (-1), 6)
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_PROVISÃO" ? Math.Round(v.Liquido, 6)
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_ESTORNO_PROVISÃO" ? Math.Round(v.Liquido, 6) 
                                    : v.Mercadoria == 0 ? 0 
                                    : Math.Round(((v.Liquido / (1 - (v.Desconto - v.Repasse) / v.Mercadoria)) - v.Liquido) * (-1), 6)), 6)
                                    - (v.Tipo.ToUpper() == "DEVOLUCAO" ? Math.Round(v.Liquido, 6) : 0),
                               TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
                                   {
                                       new TB_LANCAMENTO_VENDA()
                                       {
                                            ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.GSalesBrV].IdIndicadorVenda,
                                            ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto,
                                            QUANTIDADE_VENDA = v.Quantidade,
                                            DESCONTO  = Convert.ToDouble(v.Desconto),
                                            LIQUIDO = Convert.ToDouble(v.Liquido),
                                            MERCADORIA = Convert.ToDouble(v.Mercadoria),
                                            REPASSE = Convert.ToDouble(v.Repasse),
                                            INDICA_PROVISAO = pTipoProcesso == TipoProcesso.ImportarVenda ? true : false,
                                            NOTA = v.Nota,
                                            SERIE = v.Serie,
                                            CODIGO_CLIENTE = v.CodigoCliente,
                                            NOME_CLIENTE = v.NomeCliente,
                                            ESTADO = v.Estado,
                                            TIPO = v.Tipo
                                       }
                                   }
                           }).ToList();

            i = 0;
            iMaxItens = 0;
            foreach (var item in Lancamentos)
            {
                Lancamento.Add(item);
                if (iMaxItens >= MaxItens)
                {
                    Lancamento.Save();
                    iMaxItens = 0;
                }
                i++;
                iMaxItens++;
                OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresVendas.GSalesBrV + "...", i, Lancamentos.Count()));
            }
            Lancamento.Save();

            #endregion Indicador GSalesBrV

            GC.Collect();

            #region Indicador GSalesBrU

            Lancamentos = (from v in pListaVendas
                           select new TB_LANCAMENTO
                           {
                               CONTRATO_DESPESA_COMPROMETIDA = null,
                               DATA_INCLUSAO = DateTime.Now,
                               DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                               DESCRICAO_LANCAMENTO = string.Format("Saldo de vendas do período {0}/{1}", pMes, pAno),
                               ID_CENTRO_CUSTO = null,
                               ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresVendas.GSalesBrU].IdContaContabil,
                               ID_LANCAMENTO_TIPO = 1,
                               ID_MAPA_ESTRATEGICO_ITEM = null,
                               ID_PERIODO = IdPeriodo,
                               ID_PROJETO = null,
                               INDICA_DESPESA_COMPROMETIDA = false,
                               // Fórmula para calcular o lançamento
                               VALOR_LANCAMENTO =
                                    v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                    : v.Tipo.ToUpper() == "VENDAS" ? v.Quantidade
                                    : v.Tipo.ToUpper() == "BONIFICADO" ? v.Quantidade : 0,
                               TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
                                   {
                                       new TB_LANCAMENTO_VENDA()
                                       {
                                            ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.GSalesBrU].IdIndicadorVenda,
                                            ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto,
                                            QUANTIDADE_VENDA = v.Quantidade,
                                            DESCONTO  = Convert.ToDouble(v.Desconto),
                                            LIQUIDO = Convert.ToDouble(v.Liquido),
                                            MERCADORIA = Convert.ToDouble(v.Mercadoria),
                                            REPASSE = Convert.ToDouble(v.Repasse),
                                            INDICA_PROVISAO = pTipoProcesso == TipoProcesso.ImportarVenda ? true : false,
                                            NOTA = v.Nota,
                                            SERIE = v.Serie,
                                            CODIGO_CLIENTE = v.CodigoCliente,
                                            NOME_CLIENTE = v.NomeCliente,
                                            ESTADO = v.Estado,
                                            TIPO = v.Tipo
                                       }
                                   }
                           }).ToList();

            i = 0;
            iMaxItens = 0;
            foreach (var item in Lancamentos)
            {
                Lancamento.Add(item);
                if (iMaxItens >= MaxItens)
                {
                    Lancamento.Save();
                    iMaxItens = 0;
                }
                i++;
                iMaxItens++;
                OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresVendas.GSalesBrU + "...", i, Lancamentos.Count()));
            }
            Lancamento.Save();

            #endregion Indicador GSalesBrU

            GC.Collect();

            #region Indicador ReturnsU

            Lancamentos = (from v in pListaVendas
                           select new TB_LANCAMENTO
                           {
                               CONTRATO_DESPESA_COMPROMETIDA = null,
                               DATA_INCLUSAO = DateTime.Now,
                               DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                               DESCRICAO_LANCAMENTO = string.Format("Saldo de vendas do período {0}/{1}", pMes, pAno),
                               ID_CENTRO_CUSTO = null,
                               ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresVendas.ReturnsU].IdContaContabil,
                               ID_LANCAMENTO_TIPO = 1,
                               ID_MAPA_ESTRATEGICO_ITEM = null,
                               ID_PERIODO = IdPeriodo,
                               ID_PROJETO = null,
                               INDICA_DESPESA_COMPROMETIDA = false,
                               // Fórmula para calcular o lançamento
                               VALOR_LANCAMENTO =
                                    v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                    : v.Tipo.ToUpper() == "DEVOLUCAO" ? v.Quantidade
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_PROVISÃO" ? v.Quantidade
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_ESTORNO_PROVISÃO" ? v.Quantidade : 0,
                               TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
                                   {
                                       new TB_LANCAMENTO_VENDA()
                                       {
                                            ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.ReturnsU].IdIndicadorVenda,
                                            ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto,
                                            QUANTIDADE_VENDA = v.Quantidade,
                                            DESCONTO  = Convert.ToDouble(v.Desconto),
                                            LIQUIDO = Convert.ToDouble(v.Liquido),
                                            MERCADORIA = Convert.ToDouble(v.Mercadoria),
                                            REPASSE = Convert.ToDouble(v.Repasse),
                                            INDICA_PROVISAO = pTipoProcesso == TipoProcesso.ImportarVenda ? true : false,
                                            NOTA = v.Nota,
                                            SERIE = v.Serie,
                                            CODIGO_CLIENTE = v.CodigoCliente,
                                            NOME_CLIENTE = v.NomeCliente,
                                            ESTADO = v.Estado,
                                            TIPO = v.Tipo
                                       }
                                   }
                           }).ToList();

            i = 0;
            iMaxItens = 0;
            foreach (var item in Lancamentos)
            {
                Lancamento.Add(item);
                if (iMaxItens >= MaxItens)
                {
                    Lancamento.Save();
                    iMaxItens = 0;
                }
                i++;
                iMaxItens++;
                OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresVendas.ReturnsU + "...", i, Lancamentos.Count()));
            }
            Lancamento.Save();

            #endregion Indicador ReturnsU

            GC.Collect();

            #region Indicador GSalesArU

            Lancamentos = (from v in pListaVendas
                           select new TB_LANCAMENTO
                           {
                               CONTRATO_DESPESA_COMPROMETIDA = null,
                               DATA_INCLUSAO = DateTime.Now,
                               DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                               DESCRICAO_LANCAMENTO = string.Format("Saldo de vendas do período {0}/{1}", pMes, pAno),
                               ID_CENTRO_CUSTO = null,
                               ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresVendas.GSalesArU].IdContaContabil,
                               ID_LANCAMENTO_TIPO = 1,
                               ID_MAPA_ESTRATEGICO_ITEM = null,
                               ID_PERIODO = IdPeriodo,
                               ID_PROJETO = null,
                               INDICA_DESPESA_COMPROMETIDA = false,
                               // Fórmula para calcular o lançamento
                               VALOR_LANCAMENTO =
                                    v.Tipo.ToUpper() == "AMOSTRA" ? 0
                                    : (v.Tipo.ToUpper() == "VENDAS" ? v.Quantidade
                                    : v.Tipo.ToUpper() == "BONIFICADO" ? v.Quantidade : 0)
                                    + (v.Tipo.ToUpper() == "DEVOLUCAO" ? v.Quantidade
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_PROVISÃO" ? v.Quantidade
                                    : v.Tipo.ToUpper() == "DEVOLUCAO_ESTORNO_PROVISÃO" ? v.Quantidade : 0),
                               TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
                                   {
                                       new TB_LANCAMENTO_VENDA()
                                       {
                                            ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.GSalesArU].IdIndicadorVenda,
                                            ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto,
                                            QUANTIDADE_VENDA = v.Quantidade,
                                            DESCONTO  = Convert.ToDouble(v.Desconto),
                                            LIQUIDO = Convert.ToDouble(v.Liquido),
                                            MERCADORIA = Convert.ToDouble(v.Mercadoria),
                                            REPASSE = Convert.ToDouble(v.Repasse),
                                            INDICA_PROVISAO = pTipoProcesso == TipoProcesso.ImportarVenda ? true : false,
                                            NOTA = v.Nota,
                                            SERIE = v.Serie,
                                            CODIGO_CLIENTE = v.CodigoCliente,
                                            NOME_CLIENTE = v.NomeCliente,
                                            ESTADO = v.Estado,
                                            TIPO = v.Tipo
                                       }
                                   }
                           }).ToList();

            i = 0;
            iMaxItens = 0;
            foreach (var item in Lancamentos)
            {
                Lancamento.Add(item);
                if (iMaxItens >= MaxItens)
                {
                    Lancamento.Save();
                    iMaxItens = 0;
                }
                i++;
                iMaxItens++;
                OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresVendas.GSalesArU + "...", i, Lancamentos.Count()));
            }
            Lancamento.Save();

            #endregion Indicador GSalesArU

            GC.Collect();

            if (pTipoProcesso == TipoProcesso.SincronizarVenda)
            {
                #region Indicador StandardCosts

                Lancamentos = (from v in pListaVendas
                               where (v.CodigoProduto.Substring(0, 3) == "106" && v.CodigoProduto != "106020182" && v.CodigoProduto != "106020015")
                               select new TB_LANCAMENTO
                               {
                                   CONTRATO_DESPESA_COMPROMETIDA = null,
                                   DATA_INCLUSAO = DateTime.Now,
                                   DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                                   DESCRICAO_LANCAMENTO = string.Format("Saldo de custos do período {0}/{1}", pMes, pAno),
                                   ID_CENTRO_CUSTO = null,
                                   ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresCustos.StandardCosts].IdContaContabil,
                                   ID_LANCAMENTO_TIPO = 1,
                                   ID_MAPA_ESTRATEGICO_ITEM = null,
                                   ID_PERIODO = IdPeriodo,
                                   ID_PROJETO = null,
                                   INDICA_DESPESA_COMPROMETIDA = false,
                                   // Fórmula para calcular o lançamento
                                   VALOR_LANCAMENTO =
                                        (v.Quantidade * (decimal)(ValoresCustosUnitarios.ContainsKey(v.CodigoProduto) ? (decimal?)ValoresCustosUnitarios[v.CodigoProduto].ValorCustoUnitario : 0)),
                                   TB_LANCAMENTO_CUSTO = new TrackableCollection<TB_LANCAMENTO_CUSTO>()
                                   {
                                       new TB_LANCAMENTO_CUSTO()
                                       {
                                           ID_INDICADOR_CUSTO = (int)IndicadoresCustos[Indicadores.IndicadoresCustos.StandardCosts].IdIndicadorCusto,
                                           ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto
                                       }
                                   }
                               }).ToList();

                i = 0;
                iMaxItens = 0;
                foreach (var item in Lancamentos)
                {
                    Lancamento.Add(item);
                    if (iMaxItens >= MaxItens)
                    {
                        Lancamento.Save();
                        iMaxItens = 0;
                    }
                    i++;
                    iMaxItens++;
                    OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresCustos.StandardCosts + "...", i, Lancamentos.Count()));
                }
                Lancamento.Save();

                #endregion Indicador StandardCosts

                GC.Collect();

                #region Indicador StandardCOGS

                Lancamentos = (from v in pListaVendas
                               where (v.CodigoProduto.Substring(0, 3) == "006" || v.CodigoProduto == "106020182" || v.CodigoProduto == "106020015")
                               select new TB_LANCAMENTO
                               {
                                   CONTRATO_DESPESA_COMPROMETIDA = null,
                                   DATA_INCLUSAO = DateTime.Now,
                                   DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                                   DESCRICAO_LANCAMENTO = string.Format("Saldo de custos do período {0}/{1}", pMes, pAno),
                                   ID_CENTRO_CUSTO = null,
                                   ID_CONTA_CONTABIL = DescricoesContasContabeis[Indicadores.IndicadoresCustos.StandardCOGS].IdContaContabil,
                                   ID_LANCAMENTO_TIPO = 1,
                                   ID_MAPA_ESTRATEGICO_ITEM = null,
                                   ID_PERIODO = IdPeriodo,
                                   ID_PROJETO = null,
                                   INDICA_DESPESA_COMPROMETIDA = false,
                                   // Fórmula para calcular o lançamento
                                   VALOR_LANCAMENTO =
                                        (v.Quantidade * (decimal)(ValoresCustosUnitarios.ContainsKey(v.CodigoProduto) ? (decimal?)ValoresCustosUnitarios[v.CodigoProduto].ValorCustoUnitario : 0)),
                                   TB_LANCAMENTO_CUSTO = new TrackableCollection<TB_LANCAMENTO_CUSTO>()
                                   {
                                       new TB_LANCAMENTO_CUSTO()
                                       {
                                            ID_INDICADOR_CUSTO = (int)IndicadoresCustos[Indicadores.IndicadoresCustos.StandardCOGS].IdIndicadorCusto,
                                            ID_PRODUTO = Produtos[v.CodigoProduto].IdProduto
                                       }
                                   }
                               }).ToList();

                i = 0;
                iMaxItens = 0;
                foreach (var item in Lancamentos)
                {
                    Lancamento.Add(item);
                    if (iMaxItens >= MaxItens)
                    {
                        Lancamento.Save();
                        iMaxItens = 0;
                    }
                    i++;
                    iMaxItens++;
                    OnImportData(this, new ImportDataEventArgs("Inserindo indicador " + Indicadores.IndicadoresCustos.StandardCOGS + "...", i, Lancamentos.Count()));
                }
                Lancamento.Save();

                #endregion Indicador StandardCOGS

                GC.Collect();

                #region Calcular Amostras Grátis de Procedimento
                //TODO: Hard code no ID_LANCAMENTO_TIPO
                Lancamentos = (from v in pListaVendas
                               where v.Tipo.ToUpper() == "AMOSTRA"
                               select new TB_LANCAMENTO
                               {
                                   CONTRATO_DESPESA_COMPROMETIDA = null,
                                   DATA_INCLUSAO = DateTime.Now,
                                   DATA_LANCAMENTO = new DateTime(pAno, pMes, 1),
                                   DESCRICAO_LANCAMENTO = string.Format("Amostra Grátis de Procedimento do período {0}/{1}", pMes, pAno),
                                   ID_CENTRO_CUSTO = Produtos[v.CodigoProduto].IdCentroCusto,
                                   ID_CONTA_CONTABIL = CodigosContasContabeis["34109001"].IdContaContabil,
                                   ID_LANCAMENTO_TIPO = 9,
                                   ID_MAPA_ESTRATEGICO_ITEM = null,
                                   ID_PERIODO = IdPeriodo,
                                   ID_PROJETO = null,
                                   INDICA_DESPESA_COMPROMETIDA = false,
                                   // Fórmula para calcular o lançamento
                                   VALOR_LANCAMENTO =
                                        (v.Quantidade * (decimal)(ValoresCustosUnitarios.ContainsKey(v.CodigoProduto) ? (decimal?)ValoresCustosUnitarios[v.CodigoProduto].ValorCustoUnitario : 0)),
                                   TB_LANCAMENTO_DESPESA = new TrackableCollection<TB_LANCAMENTO_DESPESA>()
                                   {
                                       new TB_LANCAMENTO_DESPESA()
                                       {
                                           ID_INDICADOR_DESPESA = (int)IndicadoresDespesas[Indicadores.IndicadoresDespesas.Despesas].IdIndicadorDespesa,
                                           ID_PRODUTO = Produtos[v.CodigoProduto].IdProdutoPai != null ? Produtos[v.CodigoProduto].IdProdutoPai : Produtos[v.CodigoProduto].IdProduto
                                       }
                                    }
                               }).ToList();

                i = 0;
                foreach (var item in Lancamentos)
                {
                    Lancamento.Add(item);

                    i++;
                    OnImportData(this, new ImportDataEventArgs("Inserindo Amostra Grátis de Procedimento...", i, Lancamentos.Count()));
                }
                Lancamento.Save();

                #endregion Calcular Amostras Grátis de Procedimento
            }
            GC.Collect();
        }

        /// <summary>
        /// Valida Dados de Importação
        /// </summary>
        /// <param name="pCentrosCusto">Centros de Custo</param>
        /// <param name="pContasContabeis">Contas Contábeis</param>
        /// <param name="pListaVendas">Lista de Vendas</param>
        private void ValidaDadosImportacao(Dictionary<string, Produto.Lista> pProdutos, List<Lista> pListaVendas)
        {
            // Valida se os produtos estão cadastrados no sistema
            var Valida = (from p in pListaVendas
                          join db in pProdutos.Select(s => s.Value).ToList()
                          on p.CodigoProduto equals db.CodigoProduto
                          into produtos
                          from db in produtos.DefaultIfEmpty()
                          where db == null
                          select p).Count();

            if (Valida > 0)
                throw new Exception("Existem produtos não cadastrados no sistema.\nPor favor, execute a sincronização de produtos antes de importar as vendas.");

            // Valida relacionamento entre Produto Protheus e Produto Galderma Global
            ProdutoGlobal ProdutoGlobal = new ProdutoGlobal();
            var ProdutosGlobais = ProdutoGlobal.GetLista().ToList();

            var ValidaRelacionamentosProdutos = (from p in pProdutos
                                                 join db in pListaVendas
                                                 on p.Value.CodigoProduto equals db.CodigoProduto
                                                 where string.IsNullOrWhiteSpace(p.Value.CodigoProdutoGlobal)
                                                 select p).Count();

            if (ValidaRelacionamentosProdutos > 0)
                throw new Exception("Existem produtos sem relacionamento entre o código Protheus e o código Global.");

            // Valida se existe valor de custo unitário
            CustoUnitario CustoUnitario = new CustoUnitario();
            var CustosUnitarios = CustoUnitario.GetLista().ToList();

            var ValidaCustosUnitarios = (from p in pListaVendas
                                         join db in CustosUnitarios
                                         on p.CodigoProduto equals db.CodigoProduto
                                         into custosUnitarios
                                         from db in custosUnitarios.DefaultIfEmpty()
                                         where db == null
                                         select p).Count();

            if (ValidaCustosUnitarios > 0)
                throw new Exception("Existem produtos sem valor de custo unitário.");

            // Valida relacionamento entre o Produto e Produto Pai, se tipo é AG ou SEMI
            // Dictionary de Tipos de Produtos para recuperar o ID, utilizando o nome
            ProdutoTipo ProdutoTipo = new ProdutoTipo();
            var ProdutosTipos = ProdutoTipo.GetLista().ToDictionary(d => d.NomeProdutoTipo);

            Produto Produto = new Produto();
            var Produtos = Produto.GetLista().Where(w => w.IdProdutoTipo == ProdutosTipos["AG"].IdProdutoTipo || w.IdProdutoTipo == ProdutosTipos["SEMI"].IdProdutoTipo).ToList();

            var ValidaRelacionamentosTipos = (from p in pListaVendas
                                              join db in Produtos
                                              on p.CodigoProduto equals db.CodigoProduto
                                              where db.IdProdutoPai == null
                                              select p).Count();

            if (ValidaRelacionamentosTipos > 0)
                throw new Exception("Existem produtos de AG ou SEMI sem relacionamento entre Produto e Produto Pai.");
        }

        /// <summary>
        /// Executa a limpeza da tabela de lançamentos para iniciar
        /// uma nova inserção sem duplicação de dados
        /// </summary>
        /// <param name="pMes">Mês para filtro dos lançamentos</param>
        /// <param name="pAno">Ano para filtro dos lançamentos</param>
        /// <param name="pTipoProcesso">Tipo de lançamento a ser excluído</param>
        private void ExcluirLancamentosAnteriores(int pMes, int pAno, TipoProcesso pTipoProcesso)
        {
            OnImportData(this, new ImportDataEventArgs("Excluindo lançamentos anteriores..."));

            // Período do mês de importação
            Periodo Periodo = new Periodo();
            var IdPeriodo = Periodo.GetItens(new Periodo.Lista() { AnoPeriodo = pAno, MesPeriodo = pMes }).First().IdPeriodo;

            SPExcluirLancamentosAnterioresVendas ExcluirLancamentosAnterioresVendas = new SPExcluirLancamentosAnterioresVendas();
            ExcluirLancamentosAnterioresVendas.Execute(IdPeriodo, pTipoProcesso == TipoProcesso.ImportarVenda ? true : false);

            if (pTipoProcesso == TipoProcesso.SincronizarVenda)
            {
                SPExcluirLancamentosAnterioresAmostras ExcluirLancamentosAnterioresAmostras = new SPExcluirLancamentosAnterioresAmostras();
                ExcluirLancamentosAnterioresAmostras.Execute(IdPeriodo, 9);
            }
        }

        #endregion Processos

        #endregion

        #region Relatório de Indicadores de Vendas

        /// <summary>
        /// Relatório de Indicadores de Vendas
        /// </summary>
        /// <param name="pIdPeriodo">ID do Período</param>
        /// <returns>Lista</returns>
        public List<Relatorio> GerarRelatorioVendas(int[] pIdPeriodo)
        {
            // Dictionary de Indicadores de Vendas para recuperar o ID, utilizando o nome
            IndicadorVenda IndicadorVenda = new IndicadorVenda();
            var IndicadoresVendas = IndicadorVenda.GetLista().ToDictionary(d => d.NomeIndicadorVenda);

            // Dictionary de Tipos de Lançamento para recuperar o ID, utilizando o nome
            LancamentoTipo LancamentoTipo = new LancamentoTipo();
            var LancamentosTipos = LancamentoTipo.GetLista().ToDictionary(d => d.DescricaoLancamentoTipo);

            List<Relatorio> Relatorio = new List<Relatorio>();
            Lancamento Lancamento = new Lancamento();
            LancamentoVenda LancamentoVenda = new LancamentoVenda();
            Relatorio = (from l in Lancamento.GetLista(new Lancamento.Lista() { IdLancamentoTipo = LancamentosTipos["Real"].IdLancamentoTipo }).Where(w => pIdPeriodo.Contains((int)w.IdPeriodo)).Select(s => s)
                         group l by new
                         {
                             Estado = l.Estado,
                             Nota = l.Nota,
                             Serie = l.Serie,
                             Cliente = l.Cliente,
                             Nome = l.Nome,
                             CodigoProduto = l.CodigoProduto,
                             NomeProduto = l.NomeProduto,
                             CodigoProdutoGlobal = l.CodigoProdutoGlobal,
                             NomeProdutoGlobal = l.NomeProdutoGlobal,
                             NomeProdutoFamilia = l.NomeProdutoFamilia,
                             Tipo = l.Tipo
                         }
                             into gr
                             select new Relatorio()
                            {
                                Estado = gr.Key.Estado,
                                Nota = gr.Key.Nota,
                                Serie = gr.Key.Serie,
                                Cliente = gr.Key.Cliente,
                                Nome = gr.Key.Nome,
                                Tipo = gr.Key.Tipo,
                                CodigoProduto = gr.Key.CodigoProduto,
                                NomeProduto = gr.Key.NomeProduto,
                                CodigoProdutoGlobal = gr.Key.CodigoProdutoGlobal,
                                NomeProdutoGlobal = gr.Key.NomeProdutoGlobal,
                                NomeProdutoFamilia = gr.Key.NomeProdutoFamilia,
                                Volumes = gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.GSalesBrU].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento), // GSales b.r. (u)
                                ReturnsUnit = gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.ReturnsU].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento), // Returns (u)
                                VolumeAfterReturns =
                                    gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.GSalesBrU].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento)
                                    + gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.ReturnsU].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento), // GSales b.r. (u) + Returns (u)
                                GrossSales = gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.GSalesBrV].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento), // GSales b.r. (V)
                                ReturnAmount = gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.ReturnsV].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento), // Returns (V)
                                TotalOthersRevenue = null,
                                OthersRevenue = null,
                                GrossProceedOfSales =
                                    gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.GSalesBrV].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento)
                                    + gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.ReturnsV].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento), // GSales b.r. (V) + Returns (V)
                                TotalGeneralPriceReduction = gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.OthCredRebV].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento), // Oth.Cred/Reb. (V)
                                NetProceedsOfSales =
                                    gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.OthCredRebV].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento)
                                    + (gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.GSalesBrV].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento)
                                    + gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.ReturnsV].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento)), // Oth.Cred/Reb. (V) + (GSales b.r. (V) + Returns (V))
                                TotalPerfTrade = gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.TradeAllowances].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento), // Trade Allowances
                                CashDiscount = null,
                                NetSales = gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.NetSales].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento), // Net Sales
                                ListPrice = null,
                                VolumesAfterReturn = null,
                                NetNetSales =
                                    gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.NetSales].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento)
                                    - gr.Where(w => w.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.TradeAllowances].IdIndicadorVenda).Sum(s => (double)s.ValorLancamento) // Net Sales + Trade Allowances
                            }).ToList();

            return Relatorio;
        }

        #endregion Relatório de Indicadores de Vendas

        #region Classes

        /// <summary>
        /// Lista com as propriedades da classe
        /// </summary>
        public class Lista
        {
            public string Nota { get; set; }
            public string Serie { get; set; }
            public string CodigoCliente { get; set; }
            public string NomeCliente { get; set; }
            public string Estado { get; set; }
            public int IdProduto { get; set; }
            public int IdLancamento { get; set; }
            public int IdLancamentoVenda { get; set; }
            public int IdContaContabil { get; set; }
            public int IdCentroCusto { get; set; }
            public string CodigoProduto { get; set; }
            public string NomeProduto { get; set; }
            public decimal ValorLancamento { get; set; }
            public string Tipo { get; set; }
            public int Quantidade { get; set; }
            public decimal Mercadoria { get; set; }
            public decimal Repasse { get; set; }
            public decimal Desconto { get; set; }
            public decimal Liquido { get; set; }
        }

        /// <summary>
        /// 
        /// </summary>
        public class Relatorio
        {
            public string Estado { get; set; }
            public string Nota { get; set; }
            public string Serie { get; set; }
            public string Cliente { get; set; }
            public string Nome { get; set; }
            public string CodigoProduto { get; set; }
            public string NomeProduto { get; set; }
            public string CodigoProdutoGlobal { get; set; }
            public string NomeProdutoGlobal { get; set; }
            public string NomeProdutoFamilia { get; set; }
            public string Tipo { get; set; }
            public double? Volumes { get; set; } // GSales b.r. (u)
            public double? ReturnsUnit { get; set; } // Returns (u)
            public double? VolumeAfterReturns { get; set; } // GSales b.r. (u) + Returns (u)
            public double? GrossSales { get; set; } // GSales b.r. (V)
            public double? ReturnAmount { get; set; } // Returns (V)
            public double? TotalOthersRevenue { get; set; } // null
            public double? OthersRevenue { get; set; } // null
            public double? GrossProceedOfSales { get; set; } // GSales b.r. (V) + Returns (V)
            public double? TotalGeneralPriceReduction { get; set; } //Oth.Cred/Reb. (V)
            public double? NetProceedsOfSales { get; set; } // Oth.Cred/Reb. (V) + (GSales b.r. (V) + Returns (V))
            public double? TotalPerfTrade { get; set; } // Trade Allowances
            public double? CashDiscount { get; set; } // null
            public double? NetSales { get; set; } // Net Sales
            public double? ListPrice { get; set; } // null
            public double? VolumesAfterReturn { get; set; } // null
            public double? NetNetSales { get; set; } // Net Sales + Trade Allowances
        }

        #endregion Classes

        public event ImportDataEventHandler OnImportData;
    }
}